package com.youlu.campus.service.wechat.impl;

import com.alibaba.fastjson.JSONObject;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.common.utils.RedisKeyUtil;
import com.youlu.campus.entity.VO.req.WechatConfigInfoQueryVO;
import com.youlu.campus.entity.WechatConfigInfo;
import com.youlu.campus.entity.platform.PlatformSubConfigure;
import com.youlu.campus.service.platform.PlatformSubConfigureService;
import com.youlu.campus.service.wechat.WechatConfigInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

@Slf4j
@Service
public class WechatConfigInfoServiceImpl implements WechatConfigInfoService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private PlatformSubConfigureService platformSubConfigureService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public WechatConfigInfo find(String appId) {
        log.info(":>>> 开始获取微信配置信息:{}", appId);
        if (StringUtils.isBlank(appId)) {
            throw new BusinessException("服务器配置错误,请联系管理员");
        }
        String key = RedisKeyUtil.getWechatConfigInfoKey(appId);
        String s = redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(s)) {
            return JSONObject.parseObject(s, WechatConfigInfo.class);
        }
        Query query = new Query().addCriteria(Criteria.where("appId").is(appId));
        WechatConfigInfo we = mongoTemplate.findOne(query, WechatConfigInfo.class);
        if (Objects.isNull(we)) {
            throw new BusinessException("服务器配置错误,请联系管理员");
        }
        redisTemplate.opsForValue().set(key, JSONObject.toJSONString(we), 30, TimeUnit.MINUTES);
        return we;
    }

    @Override
    public Page<WechatConfigInfo> list(WechatConfigInfoQueryVO req) {
        log.info(":>>>  开始获取微信配置:{}", req);
        Query query = new Query();
        if (StringUtils.isNotBlank(req.getAppId())) {
            query.addCriteria(Criteria.where("appId").is(req.getAppId()));
        }
        if (StringUtils.isNotBlank(req.getName())) {
            Pattern pattern = Pattern.compile("^.*" + req.getName() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("name").regex(pattern));
        }
        if (Objects.nonNull(req.getEnable())) {
            query.addCriteria(Criteria.where("enable").is(req.getEnable()));
        }
        if (Objects.nonNull(req.getForPay())) {
            query.addCriteria(Criteria.where("forPay").is(req.getForPay()));
        }
        if (Objects.nonNull(req.getUsedAuthorize())) {
            query.addCriteria(Criteria.where("usedAuthorize").is(req.getUsedAuthorize()));
        }
        if (Objects.nonNull(req.getUsedSubscribe())) {
            query.addCriteria(Criteria.where("usedSubscribe").is(req.getUsedSubscribe()));
        }
        query.addCriteria(Criteria.where("deleted").ne(true));
        long count = mongoTemplate.count(query, WechatConfigInfo.class);
        PageRequest pageRequest = PageRequest.of(req.getPage() - 1, req.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "createdTime"));
        Sort sort = Sort.by(Sort.Direction.DESC, "createdTime");
        query.with(sort);
        List<WechatConfigInfo> datas = mongoTemplate.find(query.with(pageRequest), WechatConfigInfo.class);
        return PageableExecutionUtils.getPage(datas, pageRequest, () -> count);
    }

    @Override
    public boolean create(@NotNull WechatConfigInfo req) {
        req.setId(null);
        req.setCreatedTime(new Date());
        req = mongoTemplate.insert(req);
        if (Boolean.TRUE.equals(req.getUsedSubscribe())) {
            PlatformSubConfigure p = platformSubConfigureService.findByAppId(req.getAppId());
            if (Objects.isNull(p)) {
                p = new PlatformSubConfigure();
                p.setAppId(req.getAppId());
                p.setEnable(true);
                p.setSubOpen(true);
                platformSubConfigureService.create(p);
            } else {
                p.setSubOpen(true);
                p.setEnable(true);
                platformSubConfigureService.update(p);
            }
        }
        if (StringUtils.isNotBlank(req.getId())) {
            return true;
        }
        return false;
    }

    @Override
    public boolean update(WechatConfigInfo req) {
        Query query = new Query().addCriteria(Criteria.where("id").is(req.getId()));
        if (StringUtils.isNotBlank(req.getFirmSpecific())) {
            query.addCriteria(Criteria.where("firmSpecific").is(req.getFirmSpecific()));
        }
        WechatConfigInfo wechatConfigInfo = mongoTemplate.findOne(query, WechatConfigInfo.class);

        if (StringUtils.isNotBlank(req.getName())) {
            wechatConfigInfo.setName(req.getName());
        }
        if (StringUtils.isNotBlank(req.getAppId())) {
            wechatConfigInfo.setAppId(req.getAppId());
        }
        if (StringUtils.isNotBlank(req.getAppSecret())) {
            wechatConfigInfo.setAppSecret(req.getAppSecret());
        }
        if (Objects.nonNull(req.getEnable())) {
            wechatConfigInfo.setEnable(req.getEnable());
        }
        if (Objects.nonNull(req.getForPay())) {
            wechatConfigInfo.setForPay(req.getForPay());

        }
        if (Objects.nonNull(req.getUsedAuthorize())) {
            wechatConfigInfo.setUsedAuthorize(req.getUsedAuthorize());
        }
        if (Objects.nonNull(req.getUsedSubscribe())) {
            wechatConfigInfo.setUsedSubscribe(req.getUsedSubscribe());

        }
        if (StringUtils.isNotBlank(req.getRemark())) {
            wechatConfigInfo.setRemark(req.getRemark());

        }
        if (Objects.nonNull(req.getPriority())) {
            wechatConfigInfo.setPriority(req.getPriority());
        }
        if (Objects.nonNull(req.getMerchantIds())) {
            wechatConfigInfo.setMerchantIds(req.getMerchantIds());
        }
        wechatConfigInfo.setUpdatedTime(new Date());
        mongoTemplate.save(wechatConfigInfo);
        if (Boolean.TRUE.equals(req.getUsedSubscribe())) {
            PlatformSubConfigure p = platformSubConfigureService.findByAppId(req.getAppId());
            if (Objects.isNull(p)) {
                p = new PlatformSubConfigure();
                p.setAppId(req.getAppId());
                p.setEnable(true);
                p.setSubOpen(true);
                platformSubConfigureService.create(p);
            } else {
                p.setSubOpen(true);
                p.setEnable(true);
                platformSubConfigureService.update(p);
            }
        }
        deleteCache(wechatConfigInfo.getAppId());
        return true;
    }

    @Override
    public boolean delete(String id) {
        WechatConfigInfo w = mongoTemplate.findById(id, WechatConfigInfo.class);
        if (Objects.isNull(w)) {
            return true;
        }
        w.setDeleted(true);
        w.setUpdatedTime(new Date());
        mongoTemplate.save(w);
        deleteCache(w.getAppId());
        return true;
    }

    @Override
    public WechatConfigInfo findOne(String id) {
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        return mongoTemplate.findOne(query, WechatConfigInfo.class);
    }

    private void deleteCache(String appId) {
        if (StringUtils.isBlank(appId)) {
            return;
        }
        String key = RedisKeyUtil.getWechatConfigInfoKey(appId);
        redisTemplate.delete(key);
    }
}